package org.biz.modules.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.biz.common.CommonConstant;
import org.biz.common.Result;
import org.biz.config.RedisCache;
import org.biz.modules.entity.*;
import org.biz.modules.mapper.VerifyCodeMapper;
import org.biz.modules.service.SysRoleService;
import org.biz.modules.service.SysUserService;
import org.biz.util.JwtUtil;
import org.biz.util.UserContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author zf
 * @ClassName LoginController
 */
@RestController
@RequestMapping("/api")
public class LoginController {

    @Resource
    private SysUserService sysUserService;
    @Resource
    private SysRoleService sysRoleService;
    @Resource
    private AuthenticationManager authenticationManager;
    @Resource
    private RedisCache redisCache;
    @Autowired
    private VerifyCodeMapper verifyCodeMapper;

    @Value("${aliyun.acs.templateCode:}")
    private String templateCode;
    @Value("${aliyun.acs.templateCodeLogin}")
    private String templateCodeLogin;
    @Value("${data.year}")
    private String dataYear;

    /** 手机验证码暂存 **/
//    private final Map<String, String> codeMap = new HashMap<>();

    /**
     *登录
     *
     **/
    @PostMapping("/login")
    @ApiOperation(notes = "", value = "登录")
    public Result<?> login(@RequestBody LoginModel loginModel) {
        String mobile = loginModel.getMobile();
        String name = loginModel.getName();
        String idCard = loginModel.getIdCard();
        String pwd = loginModel.getPwd();
        LoginUserVO vo = new LoginUserVO();
        SysUser user;
        List<SysRole> roleList = null;
        UsernamePasswordAuthenticationToken authenticationToken;
        try {
            //管理员登录校验=手机+密码
            if (StringUtils.isNotBlank(mobile)){
                user = sysUserService.getOne(new QueryWrapper<SysUser>()
                        .lambda()
                        .eq(SysUser::getMobile, mobile.trim())
                        .eq(SysUser::getPwd,pwd.trim())
                        .eq(SysUser::getDataYear,dataYear)
                );
                if (user == null){
                    return Result.error("手机号或密码错误，登录失败！");
                }
                roleList = sysRoleService.getRoleListByUserId(user.getId());
                authenticationToken = new UsernamePasswordAuthenticationToken(user.getMobile(),"{noop}"+user.getPwd());
            }
            //普通用户登录校验=姓名+身份证
            else{
                user = sysUserService.getOne(new QueryWrapper<SysUser>()
                        .lambda()
                        .eq(SysUser::getName, name.trim())
                        .eq(SysUser::getIdCard,idCard.trim())
                        .eq(SysUser::getDataYear,dataYear)
                );
                if (user == null){
                    return Result.error("登录失败，您的资料不在省级专科护士数据库中，请联系平台工作人员！");
                }
                //添加身份证
                UserContext.setIdCard(idCard);
                authenticationToken = new UsernamePasswordAuthenticationToken(user.getName(),"{noop}"+user.getIdCard());
            }

            vo.setSysUser(user);
            vo.setRoleList(roleList);
            Authentication authenticate = authenticationManager.authenticate(authenticationToken);
            //判断是否认证通过
            if(Objects.isNull(authenticate)){
                return Result.error("用户名或密码错误!");
            }
            //获取userId,生成token
            LoginUserVO loginUser = (LoginUserVO) authenticate.getPrincipal();
            loginUser.setRoleList(roleList);
            String userId = loginUser.getSysUser().getId();
            String jwt = JwtUtil.createJWT(userId);
            loginUser.setToken(jwt);
            if (StringUtils.isNotBlank(user.getPwd())){
                loginUser.getSysUser().setPwd(user.getPwd());
            }
            //把用户信息存入redis
            redisCache.setCacheObject(CommonConstant.KEY_LOGIN_USER + userId,loginUser,120,TimeUnit.MINUTES);
            return Result.OK(loginUser);

        }finally {
            UserContext.clear();
        }


    }

//    /**
//    *获取验证码
//    *
//     * @param mobile 手机号
//     **/
//    @GetMapping("/getCaptcha")
//    @ApiOperation(value = "获取验证码")
//    public Result<?> getCaptcha(@RequestParam("mobile") String mobile) {
//        if (StringUtils.isBlank(mobile)) {
//            return Result.error("手机号不能为空！");
//        }
//        //生成6位随机验证码
//        Random random = new Random();
//        int randomCode = random.nextInt(900000) + 100000;
//        String code = String.valueOf(randomCode);
//        codeMap.put(mobile, code);
//
//        System.out.println("发送短信=========="+code);
//
//        //验证码5分钟后失效
//        ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
//        executorService.schedule(()->{
//            codeMap.remove(mobile);
//            System.out.println(code+"验证码失效");
//        },5, TimeUnit.MINUTES);
//        return Result.OK(code);
//    }

    /**
    *重置密码
    *
     * @param mobile 手机号
     * @param code 验证码
     * @param newPwd 新密码
     * @param confirmPwd 确认新密码
     **/
    @PutMapping("/resetPwd")
    @ApiOperation(value = "重置密码")
    public Result<?> resetPwd(@ApiParam("手机号") @RequestParam("mobile") String mobile,
                              @ApiParam("验证码") @RequestParam("code") String code,
                              @ApiParam("新密码") @RequestParam("newPwd") String newPwd,
                              @ApiParam("确认新密码") @RequestParam("confirmPwd") String confirmPwd) {
        if (StringUtils.isBlank(mobile)) {
            return Result.error("手机号不能为空！");
        }
        SysUser one = sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getMobile, mobile), false);
        if (one == null) {
            return Result.error("手机号未绑定，请先绑定手机号！");
        }
        VerifyCode verifyCode = verifyCodeMapper.selectByTemplateCodeAndPhone(mobile, templateCode);

        if (!StringUtils.equals(String.valueOf(verifyCode.getCode()),code)) {
            return Result.error("验证码错误！");
        }
        if (!StringUtils.equals(newPwd,confirmPwd)){
            return Result.error("两次密码不一致，重新输入！");
        }
        UpdateWrapper<SysUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("mobile",mobile);
        updateWrapper.set("pwd",newPwd);
        boolean update = sysUserService.update(updateWrapper);
        if (update) {
            return Result.OK("密码重置成功！");
        }else{
            return Result.error("密码重置失败！");
        }

    }

    @PutMapping("/bindMobile")
    @ApiOperation(value = "绑定手机号")
    public Result<?> bindMobile(@RequestParam("mobile") @ApiParam("手机号") String mobile,
                                @RequestParam("userId") @ApiParam("学员ID") String userId) {
        if (StringUtils.isBlank(userId)) {
            return Result.error("学员ID不能为空！");
        }
        if (StringUtils.isBlank(mobile)) {
            return Result.error("手机号不能为空！");
        }
        UpdateWrapper<SysUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", userId);
        updateWrapper.set("mobile", mobile);
        updateWrapper.set("update_time", LocalDateTime.now());
        sysUserService.update(updateWrapper);
        return Result.OK();
    }

    @PutMapping("/addPwd")
    @ApiOperation(value = "添加密码")
    public Result<?> addPwd(@RequestParam("newPwd") @ApiParam("新密码")String newPwd,
                             @RequestParam("confirmPwd") @ApiParam("确认新密码")String confirmPwd,
                                @RequestParam("userId") @ApiParam("学员ID") String userId) {
        if (StringUtils.isBlank(userId)) {
            return Result.error("学员ID不能为空！");
        }
        if (!StringUtils.equals(newPwd,confirmPwd)){
            return Result.error("两次密码不一致，重新输入！");
        }
        UpdateWrapper<SysUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", userId);
        updateWrapper.set("pwd", confirmPwd);
        updateWrapper.set("update_time", LocalDateTime.now());
        sysUserService.update(updateWrapper);
        return Result.OK();
    }

    @GetMapping("/loginValid")
    @ApiOperation(value = "登录二次验证")
    public Result<?> loginValid(@RequestParam("mobile") @ApiParam("手机号") String mobile,
                                @RequestParam("code") @ApiParam("验证码") String code,
                                @RequestParam("userId") @ApiParam("学员ID") String userId) {
        if (StringUtils.isBlank(userId)) {
            return Result.error("学员ID不能为空！");
        }
        if (StringUtils.isBlank(mobile)) {
            return Result.error("手机号不能为空！");
        }
        if (StringUtils.isBlank(code)) {
            return Result.error("验证码不能为空！");
        }
        SysUser sysUser = sysUserService.getById(userId);
        if (sysUser == null) {
            return Result.error("用户不存在！");
        }
        if (!StringUtils.equals(mobile, sysUser.getMobile())) {
            return Result.error("手机号尚未绑定，请先绑定手机号！");
        }

        VerifyCode verifyCode = verifyCodeMapper.selectByTemplateCodeAndPhone(mobile, templateCodeLogin);
        if (!StringUtils.equals(String.valueOf(verifyCode.getCode()),code)) {
            return Result.error("验证码错误！");
        }
        return Result.OK();
    }

    @GetMapping("/loginValidPwd")
    @ApiOperation(value = "登录二次验证-密码验证")
    public Result<?> loginValidPwd(@RequestParam("pwd") @ApiParam("密码") String pwd,
                                @RequestParam("userId") @ApiParam("学员ID") String userId) {
        if (StringUtils.isBlank(userId)) {
            return Result.error("学员ID不能为空！");
        }
        if (StringUtils.isBlank(pwd)) {
            return Result.error("密码不能为空！");
        }

        SysUser sysUser = sysUserService.getById(userId);
        if (sysUser == null) {
            return Result.error("用户不存在！");
        }
        if (!StringUtils.equals(pwd, sysUser.getPwd())) {
            return Result.error("密码错误！");
        }
        return Result.OK();
    }


}
